import std/[json, httpclient, os, times, strutils]

type
  Mirror = tuple
    name: string
    url: string
    mtype: string
    rawUrl: string


proc getPackages(m: Mirror): bool =
  var file = "https://raw.githubusercontent.com/nim-lang/packages/master/packages.json"
  case m[2]
  of "replace":
    file = file.replace("https://raw.githubusercontent.com", m[3])
  else:
    file = m[1] & "/" & file
  var client = newHttpClient(timeout = 4000)
  try:
    let content = client.getContent(file)
    writeFile("./packages.json", content)
    return true
  finally:
    client.close()
  false

proc clean() =
  for f in walkDir("."):
    if f.kind == PathComponent.pcFile and f.path.contains("packages"):
      removeFile(f.path)

proc getMirrors(): seq[Mirror] =
  let path = "./gh-mirrors.json"
  let content = readFile(path)
  let json = parseJson(content)
  var mirrors = newSeq[Mirror]()
  for a in json["mirrors"]:
    mirrors.add((name: a["name"].getStr(), url: a["url"].getStr(), mtype: a["type"].getStr(), rawUrl: a{"raw-url"}.getStr("")))
  return mirrors

proc testMirror(mirror: string, mtype: string = "append", rurl: string): int =
  let file = "https://raw.githubusercontent.com/nim-lang/packages/master/LICENSE.txt"
  var client = newHttpClient(timeout = 4000)
  try:
    let time = cpuTime()
    var content: string
    case mtype
    of "append":
      content = client.getContent(mirror & "/" & file)
    of "replace":
      content = client.getContent(file.replace("https://raw.githubusercontent.com", rurl))
    if content.len() == 18656:
      return int(cpuTime() - time)
  except CatchableError:
    echo "请求发生错误"
  finally:
    client.close()
  return 9999

proc generatePackages(name: string, url: string, mtype: string = "append"): bool =
  let packages = parseJson(readFile("./packages.json"))
  for p in packages:
    if p{"method"}.getStr("") == "git" and p{"url"}.getStr("").startsWith("https://github.com/"):
      case mtype
      of "append":
        p["url"] = %* (url & "/" & p["url"].getStr())
      of "replace":
        p["url"] = %* (p["url"].getStr().replace("https://github.com", url))
      else:
        raise newException(OSError, "不能理解的类型")
  writeFile("packages." & name & ".json", pretty(packages))
  discard

when isMainModule:
  echo("China Nim packages Mirror")
  clean()
  echo "读取镜像配置"
  let mirrors = getMirrors()
  echo "镜像测速:"
  var fast: Mirror
  var delay = 999
  for m in mirrors:
    let t = testMirror(m[1], m[2], m[3])
    echo m[1], " - ", t
    if t < delay:
      fast = m
      delay = t
  if getPackages(fast):
    echo "拉取packages.json成功"
  for m in mirrors:
    echo "生成镜像", " - ", m[1]
    discard generatePackages(m[0], m[1], m[2])
  echo "生成最佳镜像(best): ", fast[0]
  discard generatePackages("best", fast[1], fast[2])
